#pragma once

#include <vector>
#include <iostream>
#include "Sem.hpp"
#include "Mutex.hpp"
using namespace MutexModule;
const static int g_cap = 5;
using namespace SemRingModule;
template <class T>
class RingQueue
{
public:
    RingQueue(int cap = g_cap) : _cap(cap),
                                 _queue(cap),
                                 _sem_blank(cap), // 初始值为cap
                                 _sem_data(0),    // 初始值为0
                                 P_step(0),
                                 C_step(0)
    {
    }
    void Equeue(const T &item)
    {

        // 入队逻辑
        // 1 申请信号量 ，空位置信号量
        _sem_blank.P();
        {
            // _p_lock.Lock();
            LockGuard lg(_p_lock);

            // 2 放数据
            _queue[P_step] = item;
            P_step = (P_step + 1) % _cap;
            // 3 释放数据位置的信号量
            _sem_data.V();
        }
        //_p_lock.Unlock();
    }

    void Pop(T *item)
    {

        // 出队逻辑
        // 1 申请数据位置的信号量
        _sem_data.P();
        // 先进行预定在进行 上锁
        //  _c_lock.Lock();
        LockGuard lg(_c_lock);
        // 2 取数据
        *item = _queue[C_step];
        C_step = (C_step + 1) % _cap;
        // 3 释放空位置信号量
        _sem_blank.V();
        //_c_lock.Unlock();
    }

private:
    std::vector<T> _queue;
    size_t _cap = 0;

    // 生产者
    SemRing _sem_blank; // 表示空位的信号量
    int P_step;
    // 消费者
    SemRing _sem_data; // 表示数据的信号量
    int C_step;

    // 维护多生产 多消费的互斥   2把锁
    Mutex _p_lock;
    Mutex _c_lock;
};